package edu.bbte;

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.WindowConstants;

/**
 * Osztaly, amely grafikus feluletet tartalmaz.
 *  Segitsegevel adott meretu soma kocka kirakosokat lehet generalni es elmenteni azokat fajlokba, 
 *  hogy majd onnan olvassuk ki oket a jatszashoz (megjeleniteshez).
 *  
 * @author      Robert Rill
 * @version     2011.0603
 * @since       1.6
 */
public class CreateCubes {
	/**A fo keret, mely tartalmazza a grafikus komponenseket.*/
	private JFrame frame;
	/**Gombok:
	 * 		general - kocka kirakos generalasara,
	 * 		kilep - a jatekbol valo kilepeshez,
	 * 		jatek - a jatek (megjelenites) elinditasahoz.
	 * */
	private JButton general, kilep, jatek;
	/**Panelek:
	 * 		content - a fo keret kontenere,
	 * 		radioPanel - a radiogombok tarolasara, melyek a meret kivalasztasahoz szuksegesek,
	 * 		p - a kepet tartalmazza.
	 * */
	private JPanel content, radioPanel, p;
	/**Cimke, mely a hatterkepet tartalmazza.*/
	private JLabel image;
	/**Radiogombok, melyek a kocka meretenek kivalasztasahoz szuksegesek.*/
	private JRadioButton rb3, rb4, rb5, rb6;
	/**A radiogombok csoportos, egyseges kezelese.*/
	private ButtonGroup bgroup;

	/**A kocka kirakos megoldasanak eloallitasahoz szukseges osztaly.*/
	private SolveCube solve;
	/**A kocka kirakos generalasahoz szukseges osztaly.*/
	private CubeBuilder build;
	/**A kocka kirakor fajlokba valo kiiratasahoz szukseges osztaly.*/
	private CubeRW rw;
	/**A generalt es a megoldott puzzle-darabok tarolasara alkalmas tombok.*/
	private Matrix3D [] cubes, solution;

	/**
	 * Az osztaly konstruktora. Letrehozza a grafikus komponenseket, megjeleniti oket a fo kereten
	 * es figyeli a gombok mukodeset.
	 * */
	public CreateCubes() {
		createComponents();
		addComponents();
		setProperties();
		gombFigyelok();
	}
	
	/**
	 * A grafikus komponensek letrehozasaert felelos metodus. Peldanyositja a fo keretet, a gombokat, 
	 * a radiogombokat es az azokhoz szukseges panelt, lekeri a hatterkepet.
	 * */
	private void createComponents() {
		frame = new JFrame("Soma kockak generalasa");
		general = new JButton("General");
		kilep = new JButton("Kilepes");
		jatek = new JButton("Jatek");
		content = new JPanel();
		content.setLayout(null);
		frame.setContentPane(content);
		radioPanel = new JPanel();
		radioPanel.setLayout(new GridLayout(4, 1, 20, 3));
		rb3 = new JRadioButton("3", true);
		rb4 = new JRadioButton("4", false);
		rb5 = new JRadioButton("5", false);
		rb6 = new JRadioButton("6", false);
		bgroup = new ButtonGroup();	
		p = new JPanel();
		p.setLayout(null);
		image = new JLabel(new ImageIcon("soma7.jpg"));
	}
	
	/**
	 * A grafikus komponensek fo kerethez valo hozzaadasaert felelos metodus.
	 */
	private void addComponents() {
		// a radiogombok hatterszinenek beallitasa
		rb3.setBackground(new Color(180,230,200));
		rb4.setBackground(new Color(180,230,200));
		rb5.setBackground(new Color(180,230,200));
		rb6.setBackground(new Color(180,230,200));
		// A 4 radiogomb hozzaadasa a gomb-csoporthoz, hogy egysegesen kezeljuk oket. 
		//	Vagyis egyszerre csak egy gomgot lehessen kijelolni.
		bgroup.add(rb3);
		bgroup.add(rb4);
		bgroup.add(rb5);
		bgroup.add(rb6);
		// a radiogombok hozzaadasa a panelhez.
		radioPanel.add(rb3);
		radioPanel.add(rb4);
		radioPanel.add(rb5);
		radioPanel.add(rb6);
		
		// a radiogombokat tartalmazo panel meretenek, helyenek es hatterenek beallitasa.
		radioPanel.setBounds(35, 30, 110, 150);
		radioPanel.setBackground(new Color(180,230,200));
		p.add(radioPanel);
		// a Generalas gomb meretenek beallitasa
		general.setBounds(35, 200, 100, 35);
		// a Generalas gomb hozzaadasa a p panelhez
		p.add(general);
		// a Kilepes gomb meretenek beallitasa
		kilep.setBounds(35, 310, 100, 35);
		// a Kilepes gomb hozzaadasa a p panelhez
		p.add(kilep);
		// a Jatek gomb meretenek beallitasa
		jatek.setBounds(35, 240, 100, 35);
		// a JATEK GOMB HOZZAADASA a p panelhez
		//p.add(jatek);
		// a p panel meretenek beallitasa
		p.setBounds(0, 0, 180, 400);
		// a p panel hatterenek beallitasa
		p.setBackground(new Color(180, 230, 255));
		// a p panel hozzaadasa a fo keret kontenerehez
		content.add(p);
		// a kepet tartalmazo cimke meretenek beallitasa
		image.setBounds(180,0,400,370);
		// a kepet tartalmazo cimke hozzaadasa a kontenerhez
		content.add(image);
	}
	
	/**
	 * A fo keret jellemzoinek beallitasaert felelos metodus.
	 */
	private void setProperties() {
		// beallitjuk a radiogombokat tartalmazo panel szelet
		radioPanel.setBorder(BorderFactory.createTitledBorder(
		           BorderFactory.createEtchedBorder(), "Valassz meretet"));
		frame.pack();
		frame.setBounds(10, 10, 600, 400);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
	}
	
	/**
	 * A gombok mukodesenek figyeleseert felelos metodus.
	 * A Generalas gomb a legfontosabb: a radiogombok segitsegevel megadott meretu 
	 * kockakirakost generalunk, eloallitjuk ennek megoldasat es kiirjuk ezeket fajlba.
	 */
	private void gombFigyelok() {
		// a Kilepes gomb figyelojenek definialasa - kilepunk a programbol
		kilep.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});
		
		// a Generalas gomb figyelojenek definialasa
		general.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				// lekerjuk a kivalasztott meretet a radiogomboktol egy metodus segitsegevel.
				int number = meret();
				// lekerjuk a rendszeridot, hogy tudjuk majd kiszamolni a generalashoz es a
				//	  megoldas eloallitasahoz szukseges idomennyiseget
				long stime=System.currentTimeMillis();
				// kocka kirakos generalasaert felelos osztaly peldanyositasa a megfelelo merettel
				//	  (a meretet a radiogomboktol kertuk le)
				build = new CubeBuilder(number);
				// kocka kirakost generalunk
				build.build();
				build.separate();
				
				// lekerjuk a generalt puzzle darabjainak szamat
				int n = build.getPieceNum();
				// letrehozunk egy tombot a darabok tarolasara
				cubes = new Matrix3D[n];
				// egyenkent lekerjuk az osszes darabot
				for (int i=0; i < n; ++i) {
					cubes[i] = new Matrix3D(number);
					cubes[i] = build.getFinalPieces()[i].getCube();
				}
				// kocka kirakos megoldasaert felelos osztaly peldanyositasa. 
				//    A parameterek az elobb generalt darabokra es ezek szamara.
				if (number!=6) { // csak akkor ha n nem 6, kulonben lefagy (Out of memory)
					solve = new SolveCube(cubes, n);
					// lekerjuk a megoldast
					solution = solve.getSolutions3D();
				}
				// letrehozzuk a fajlokba valo kiiratasert felelos osztaly egy peldanyat.
				rw = new CubeRW();
				// kiirjuk fajlokba a generalt darabokat es a megoldast
				rw.writePuzzle(cubes, solution);
				// lekerjuk ismet a rendszeridot
				long time=System.currentTimeMillis()-stime;
				// kiirunk egy uzenetet, hogy a gep munkaja veget ert es kiirjuk az eltelt idot is.
				JOptionPane.showMessageDialog(frame, "A(z) " + number + "x" + number + "x" + number + "-s meretu kocka kirakos generalasa es a megoldas megtalalasa befejezodott "+(time/1000F)+" masodperc alatt!","uzenet", 1);	
			}
		});
		
		// a Jatek gomb figyelojenek definialasa.
		jatek.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				// A Jatek gomb figyelojenek megadasa: 
				//	  inditjuk a megjelenitest, hogy jatszhassunk.
				try {
					Runtime.getRuntime().exec( "../../../../../PFFF/PFFF/bin/x86/Debug/PFFF.exe" );
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});
	}
	
	/**
	 * A kivalasztott radiogombhoz tartozo meretet teriti vissza.
	 * @return
	 */
	public int meret() {
		// feltetelezzuk, hogy a 3-as van kijelolve es megnezzuk, hogy a 4, 5, 6 kozul nincse valamelyik kijelolve
		//	  es megfeleloen allitjuk a n-t
		int n = 3;
		if (rb4.isSelected()) n = 4;
		if (rb5.isSelected()) n = 5;
		if (rb6.isSelected()) n = 6;	
		return n;
	}
	
	/**
	 * A fo metodus: egy uj peldany hozunk letre az osztalybol.
	 * Lehetoseg van egy megadott utvonal alapjan puzzle beolvasasara fajlokbol, 
	 * a megoldasanak eloallitasara es a fajlrendszerbe valo beirasara is.
	 * @param args - a parancssor argumentumai
	 */
	public static void main(String [] args) {
		new CreateCubes();		
		/*
		SolveCube solve;
		CubeRW rw;
		Matrix3D [] cubes, solution;
		rw = new CubeRW();
		cubes = rw.readPuzzleFromFile("file/1", 6, 3);
		solve = new SolveCube(cubes, 6);
		solution = solve.getSolutions3D();
		//create writer
		rw.writePuzzle(cubes, solution);
	*/
	}
}
